package com.hqd.ch03.v38.web.servlet;

import com.hqd.ch03.v38.core.Ordered;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Set;

public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered {
    private static final String HEADER_CACHE_CONTROL = "Cache-Control";


    private int order = Ordered.LOWEST_PRECEDENCE;


    private Set<?> mappedHandlers;


    private Class<?>[] mappedHandlerClasses;

    private boolean preventResponseCaching = false;

    @Override
    public int getOrder() {
        return this.order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public void setMappedHandlers(Set<?> mappedHandlers) {
        this.mappedHandlers = mappedHandlers;
    }

    /**
     * 指定异常处理器
     */
    public void setMappedHandlerClasses(Class<?>... mappedHandlerClasses) {
        this.mappedHandlerClasses = mappedHandlerClasses;
    }


    public void setPreventResponseCaching(boolean preventResponseCaching) {
        this.preventResponseCaching = preventResponseCaching;
    }


    @Override
    public ModelAndView resolveException(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        /**
         * 寻找匹配的处理器
         */
        if (shouldApplyTo(request, handler)) {
            //禁止缓存
            prepareResponse(ex, response);
            return doResolveException(request, response, handler, ex);
        } else {
            return null;
        }
    }

    /**
     * 寻找匹配的处理器
     */
    protected boolean shouldApplyTo(HttpServletRequest request, Object handler) {
        if (handler != null) {
            if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
                return true;
            }
            if (this.mappedHandlerClasses != null) {
                for (Class<?> handlerClass : this.mappedHandlerClasses) {
                    if (handlerClass.isInstance(handler)) {
                        return true;
                    }
                }
            }
        }
        return !hasHandlerMappings();
    }

    /**
     * 注册处理器
     */
    protected boolean hasHandlerMappings() {
        return (this.mappedHandlers != null || this.mappedHandlerClasses != null);
    }


    protected void prepareResponse(Exception ex, HttpServletResponse response) {
        if (this.preventResponseCaching) {
            preventCaching(response);
        }
    }

    /**
     * 防止缓存
     *
     * @param response current HTTP response
     */
    protected void preventCaching(HttpServletResponse response) {
        response.addHeader(HEADER_CACHE_CONTROL, "no-store");
    }


    protected abstract ModelAndView doResolveException(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
}
